﻿using System;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HslCommunication.BasicFramework;
using HslCommunication.Core.IMessage;
using HslCommunication.LogNet;
using HslCommunication.Reflection;

namespace HslCommunication.Core.Net
{
	/// <summary>
	/// 支持长连接，短连接两个模式的通用客户端基类 <br />
	/// Universal client base class that supports long connections and short connections to two modes
	/// </summary>
	/// <example>
	/// 无，请使用继承类实例化，然后进行数据交互，当前的类并没有具体的实现。
	/// </example>
	// Token: 0x0200013B RID: 315
	public class NetworkDoubleBase : NetworkBase, IDisposable
	{
		/// <summary>
		/// 默认的无参构造函数 <br />
		/// Default no-parameter constructor
		/// </summary>
		// Token: 0x06001B41 RID: 6977 RVA: 0x00087C0C File Offset: 0x00085E0C
		public NetworkDoubleBase()
		{
			this.InteractiveLock = new SimpleHybirdLock();
			this.connectionId = SoftBasic.GetUniqueStringByGuidAndRandom();
		}

		/// <summary>
		/// 获取一个新的消息对象的方法，需要在继承类里面进行重写<br />
		/// The method to get a new message object needs to be overridden in the inheritance class
		/// </summary>
		/// <returns>消息类对象</returns>
		// Token: 0x06001B42 RID: 6978 RVA: 0x00087CD8 File Offset: 0x00085ED8
		protected virtual INetMessage GetNewNetMessage()
		{
			return null;
		}

		/// <summary>
		/// 当前的数据变换机制，当你需要从字节数据转换类型数据的时候需要。<br />
		/// The current data transformation mechanism is required when you need to convert type data from byte data.
		/// </summary>
		/// <example>
		/// 主要是用来转换数据类型的，下面仅仅演示了2个方法，其他的类型转换，类似处理。
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ByteTransform" title="ByteTransform示例" />
		/// </example>
		// Token: 0x1700056B RID: 1387
		// (get) Token: 0x06001B43 RID: 6979 RVA: 0x00087CDC File Offset: 0x00085EDC
		// (set) Token: 0x06001B44 RID: 6980 RVA: 0x00087CF4 File Offset: 0x00085EF4
		public IByteTransform ByteTransform
		{
			get
			{
				return this.byteTransform;
			}
			set
			{
				this.byteTransform = value;
			}
		}

		/// <summary>
		/// 获取或设置连接的超时时间，单位是毫秒 <br />
		/// Gets or sets the timeout for the connection, in milliseconds
		/// </summary>
		/// <example>
		/// 设置1秒的超时的示例
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ConnectTimeOutExample" title="ConnectTimeOut示例" />
		/// </example>
		/// <remarks>
		/// 不适用于异形模式的连接。
		/// </remarks>
		// Token: 0x1700056C RID: 1388
		// (get) Token: 0x06001B45 RID: 6981 RVA: 0x00087D00 File Offset: 0x00085F00
		// (set) Token: 0x06001B46 RID: 6982 RVA: 0x00087D18 File Offset: 0x00085F18
		[HslMqttApi(HttpMethod = "GET", Description = "Gets or sets the timeout for the connection, in milliseconds")]
		public virtual int ConnectTimeOut
		{
			get
			{
				return this.connectTimeOut;
			}
			set
			{
				bool flag = value >= 0;
				if (flag)
				{
					this.connectTimeOut = value;
				}
			}
		}

		/// <summary>
		/// 获取或设置接收服务器反馈的时间，如果为负数，则不接收反馈 <br />
		/// Gets or sets the time to receive server feedback, and if it is a negative number, does not receive feedback
		/// </summary>
		/// <example>
		/// 设置1秒的接收超时的示例
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ReceiveTimeOutExample" title="ReceiveTimeOut示例" />
		/// </example>
		/// <remarks>
		/// 超时的通常原因是服务器端没有配置好，导致访问失败，为了不卡死软件，所以有了这个超时的属性。
		/// </remarks>
		// Token: 0x1700056D RID: 1389
		// (get) Token: 0x06001B47 RID: 6983 RVA: 0x00087D38 File Offset: 0x00085F38
		// (set) Token: 0x06001B48 RID: 6984 RVA: 0x00087D50 File Offset: 0x00085F50
		[HslMqttApi(HttpMethod = "GET", Description = "Gets or sets the time to receive server feedback, and if it is a negative number, does not receive feedback")]
		public int ReceiveTimeOut
		{
			get
			{
				return this.receiveTimeOut;
			}
			set
			{
				this.receiveTimeOut = value;
			}
		}

		/// <summary>
		/// 获取或是设置远程服务器的IP地址，如果是本机测试，那么需要设置为127.0.0.1 <br />
		/// Get or set the IP address of the remote server. If it is a local test, then it needs to be set to 127.0.0.1
		/// </summary>
		/// <remarks>
		/// 最好实在初始化的时候进行指定，当使用短连接的时候，支持动态更改，切换；当使用长连接后，无法动态更改
		/// </remarks>
		/// <example>
		/// 以下举例modbus-tcp的短连接及动态更改ip地址的示例
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="IpAddressExample" title="IpAddress示例" />
		/// </example>
		// Token: 0x1700056E RID: 1390
		// (get) Token: 0x06001B49 RID: 6985 RVA: 0x00087D5C File Offset: 0x00085F5C
		// (set) Token: 0x06001B4A RID: 6986 RVA: 0x00087D74 File Offset: 0x00085F74
		[HslMqttApi(HttpMethod = "GET", Description = "Get or set the IP address of the remote server. If it is a local test, then it needs to be set to 127.0.0.1")]
		public virtual string IpAddress
		{
			get
			{
				return this.ipAddress;
			}
			set
			{
				this.ipAddress = HslHelper.GetIpAddressFromInput(value);
			}
		}

		/// <summary>
		/// 获取或设置服务器的端口号，具体的值需要取决于对方的配置<br />
		/// Gets or sets the port number of the server. The specific value depends on the configuration of the other party.
		/// </summary>
		/// <remarks>
		/// 最好实在初始化的时候进行指定，当使用短连接的时候，支持动态更改，切换；当使用长连接后，无法动态更改
		/// </remarks>
		/// <example>
		/// 动态更改请参照IpAddress属性的更改。
		/// </example>
		// Token: 0x1700056F RID: 1391
		// (get) Token: 0x06001B4B RID: 6987 RVA: 0x00087D84 File Offset: 0x00085F84
		// (set) Token: 0x06001B4C RID: 6988 RVA: 0x00087D9C File Offset: 0x00085F9C
		[HslMqttApi(HttpMethod = "GET", Description = "Gets or sets the port number of the server. The specific value depends on the configuration of the other party.")]
		public virtual int Port
		{
			get
			{
				return this.port;
			}
			set
			{
				this.port = value;
			}
		}

		/// <inheritdoc cref="P:HslCommunication.Core.IReadWriteNet.ConnectionId" />
		// Token: 0x17000570 RID: 1392
		// (get) Token: 0x06001B4D RID: 6989 RVA: 0x00087DA8 File Offset: 0x00085FA8
		// (set) Token: 0x06001B4E RID: 6990 RVA: 0x00087DC0 File Offset: 0x00085FC0
		[HslMqttApi(HttpMethod = "GET", Description = "The unique ID number of the current connection. The default is a 20-digit guid code plus a random number.")]
		public string ConnectionId
		{
			get
			{
				return this.connectionId;
			}
			set
			{
				this.connectionId = value;
			}
		}

		/// <summary>
		/// 获取或设置在正式接收对方返回数据前的时候，需要休息的时间，当设置为0的时候，不需要休息。<br />
		/// Get or set the time required to rest before officially receiving the data from the other party. When it is set to 0, no rest is required.
		/// </summary>
		// Token: 0x17000571 RID: 1393
		// (get) Token: 0x06001B4F RID: 6991 RVA: 0x00087DCA File Offset: 0x00085FCA
		// (set) Token: 0x06001B50 RID: 6992 RVA: 0x00087DD2 File Offset: 0x00085FD2
		[HslMqttApi(HttpMethod = "GET", Description = "Get or set the time required to rest before officially receiving the data from the other party. When it is set to 0, no rest is required.")]
		public int SleepTime { get; set; }

		/// <summary>
		/// 当前的异形连接对象，如果设置了异形连接的话，仅用于异形模式的情况使用<br />
		/// The current alien connection object, if alien connection is set, is only used in the case of alien mode
		/// </summary>
		/// <remarks>
		/// 具体的使用方法请参照Demo项目中的异形modbus实现。
		/// </remarks>
		// Token: 0x17000572 RID: 1394
		// (get) Token: 0x06001B51 RID: 6993 RVA: 0x00087DDB File Offset: 0x00085FDB
		// (set) Token: 0x06001B52 RID: 6994 RVA: 0x00087DE3 File Offset: 0x00085FE3
		public AlienSession AlienSession { get; set; }

		/// <summary>
		/// 在读取数据之前可以调用本方法将客户端设置为长连接模式，相当于跳过了ConnectServer的结果验证，对异形客户端无效，当第一次进行通信时再进行创建连接请求。<br />
		/// Before reading the data, you can call this method to set the client to the long connection mode, which is equivalent to skipping the result verification of ConnectServer, 
		/// and it is invalid for the alien client. When the first communication is performed, the connection creation request is performed.
		/// </summary>
		/// <example>
		/// 以下的方式演示了另一种长连接的机制
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="SetPersistentConnectionExample" title="SetPersistentConnection示例" />
		/// </example>
		// Token: 0x06001B53 RID: 6995 RVA: 0x00087DEC File Offset: 0x00085FEC
		public void SetPersistentConnection()
		{
			this.isPersistentConn = true;
		}

		/// <summary>
		/// 对当前设备的IP地址进行PING的操作，返回PING的结果，正常来说，返回<see cref="F:System.Net.NetworkInformation.IPStatus.Success" /><br />
		/// PING the IP address of the current device and return the PING result. Normally, it returns <see cref="F:System.Net.NetworkInformation.IPStatus.Success" />
		/// </summary>
		/// <returns>返回PING的结果</returns>
		// Token: 0x06001B54 RID: 6996 RVA: 0x00087DF8 File Offset: 0x00085FF8
		public IPStatus IpAddressPing()
		{
			return this.ping.Value.Send(this.IpAddress).Status;
		}

		/// <summary>
		/// 尝试连接远程的服务器，如果连接成功，就切换短连接模式到长连接模式，后面的每次请求都共享一个通道，使得通讯速度更快速<br />
		/// Try to connect to a remote server. If the connection is successful, switch the short connection mode to the long connection mode. 
		/// Each subsequent request will share a channel, making the communication speed faster.
		/// </summary>
		/// <returns>返回连接结果，如果失败的话（也即IsSuccess为False），包含失败信息</returns>
		/// <example>
		///   简单的连接示例，调用该方法后，连接设备，创建一个长连接的对象，后续的读写操作均公用一个连接对象。
		///   <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="Connect1" title="连接设备" />
		///   如果想知道是否连接成功，请参照下面的代码。
		///   <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="Connect2" title="判断连接结果" />
		/// </example> 
		// Token: 0x06001B55 RID: 6997 RVA: 0x00087E28 File Offset: 0x00086028
		public OperateResult ConnectServer()
		{
			this.isPersistentConn = true;
			Socket coreSocket = this.CoreSocket;
			if (coreSocket != null)
			{
				coreSocket.Close();
			}
			OperateResult<Socket> operateResult = this.CreateSocketAndInitialication();
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				this.IsSocketError = true;
				operateResult.Content = null;
				result = operateResult;
			}
			else
			{
				this.CoreSocket = operateResult.Content;
				ILogNet logNet = base.LogNet;
				if (logNet != null)
				{
					logNet.WriteDebug(this.ToString(), StringResources.Language.NetEngineStart);
				}
				result = operateResult;
			}
			return result;
		}

		/// <summary>
		/// 使用指定的套接字创建异形客户端，在异形客户端的模式下，网络通道需要被动创建。<br />
		/// Use the specified socket to create the alien client. In the alien client mode, the network channel needs to be created passively.
		/// </summary>
		/// <param name="session">异形客户端对象，查看<seealso cref="T:HslCommunication.Core.Net.NetworkAlienClient" />类型创建的客户端</param>
		/// <returns>通常都为成功</returns>
		/// <example>
		///   简单的创建示例。
		///   <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="AlienConnect1" title="连接设备" />
		///   如果想知道是否创建成功。通常都是成功。
		///   <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="AlienConnect2" title="判断连接结果" />
		/// </example> 
		/// <remarks>
		/// 不能和之前的长连接和短连接混用，详细参考 Demo程序 
		/// </remarks>
		// Token: 0x06001B56 RID: 6998 RVA: 0x00087EAC File Offset: 0x000860AC
		public OperateResult ConnectServer(AlienSession session)
		{
			this.isPersistentConn = true;
			this.isUseSpecifiedSocket = true;
			bool flag = session != null;
			OperateResult result;
			if (flag)
			{
				AlienSession alienSession = this.AlienSession;
				if (alienSession != null)
				{
					Socket socket = alienSession.Socket;
					if (socket != null)
					{
						socket.Close();
					}
				}
				bool flag2 = string.IsNullOrEmpty(this.ConnectionId);
				if (flag2)
				{
					this.ConnectionId = session.DTU;
				}
				bool flag3 = this.ConnectionId == session.DTU;
				if (flag3)
				{
					this.CoreSocket = session.Socket;
					this.IsSocketError = !session.IsStatusOk;
					this.AlienSession = session;
					bool isStatusOk = session.IsStatusOk;
					if (isStatusOk)
					{
						result = this.InitializationOnConnect(session.Socket);
					}
					else
					{
						result = new OperateResult();
					}
				}
				else
				{
					this.IsSocketError = true;
					result = new OperateResult();
				}
			}
			else
			{
				this.IsSocketError = true;
				result = new OperateResult();
			}
			return result;
		}

		/// <summary>
		/// 手动断开与远程服务器的连接，如果当前是长连接模式，那么就会切换到短连接模式<br />
		/// Manually disconnect from the remote server, if it is currently in long connection mode, it will switch to short connection mode
		/// </summary>
		/// <returns>关闭连接，不需要查看IsSuccess属性查看</returns>
		/// <example>
		/// 直接关闭连接即可，基本上是不需要进行成功的判定
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ConnectCloseExample" title="关闭连接结果" />
		/// </example>
		// Token: 0x06001B57 RID: 6999 RVA: 0x00087F90 File Offset: 0x00086190
		public OperateResult ConnectClose()
		{
			OperateResult result = new OperateResult();
			this.isPersistentConn = false;
			this.InteractiveLock.Enter();
			try
			{
				result = this.ExtraOnDisconnect(this.CoreSocket);
				Socket coreSocket = this.CoreSocket;
				if (coreSocket != null)
				{
					coreSocket.Close();
				}
				this.CoreSocket = null;
				this.InteractiveLock.Leave();
			}
			catch
			{
				this.InteractiveLock.Leave();
				throw;
			}
			ILogNet logNet = base.LogNet;
			if (logNet != null)
			{
				logNet.WriteDebug(this.ToString(), StringResources.Language.NetEngineClose);
			}
			return result;
		}

		/// <summary>
		/// 根据实际的协议选择是否重写本方法，有些协议在创建连接之后，需要进行一些初始化的信号握手，才能最终建立网络通道。<br />
		/// Whether to rewrite this method is based on the actual protocol. Some protocols require some initial signal handshake to establish a network channel after the connection is created.
		/// </summary>
		/// <param name="socket">网络套接字</param>
		/// <returns>是否初始化成功，依据具体的协议进行重写</returns>
		/// <example>
		/// 有些协议不需要握手信号，比如三菱的MC协议，Modbus协议，西门子和欧姆龙就存在握手信息，此处的例子是继承本类后重写的西门子的协议示例
		/// <code lang="cs" source="HslCommunication_Net45\Profinet\Siemens\SiemensS7Net.cs" region="NetworkDoubleBase Override" title="西门子重连示例" />
		/// </example>
		// Token: 0x06001B58 RID: 7000 RVA: 0x0000A76D File Offset: 0x0000896D
		protected virtual OperateResult InitializationOnConnect(Socket socket)
		{
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 根据实际的协议选择是否重写本方法，有些协议在断开连接之前，需要发送一些报文来关闭当前的网络通道<br />
		/// Select whether to rewrite this method according to the actual protocol. Some protocols need to send some packets to close the current network channel before disconnecting.
		/// </summary>
		/// <param name="socket">网络套接字</param>
		/// <example>
		/// 目前暂无相关的示例，组件支持的协议都不用实现这个方法。
		/// </example>
		/// <returns>当断开连接时额外的操作结果</returns>
		// Token: 0x06001B59 RID: 7001 RVA: 0x0000A76D File Offset: 0x0000896D
		protected virtual OperateResult ExtraOnDisconnect(Socket socket)
		{
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 和服务器交互完成的时候调用的方法，可以根据读写结果进行一些额外的操作，具体的操作需要根据实际的需求来重写实现<br />
		/// The method called when the interaction with the server is completed can perform some additional operations based on the read and write results. 
		/// The specific operations need to be rewritten according to actual needs.
		/// </summary>
		/// <param name="read">读取结果</param>
		// Token: 0x06001B5A RID: 7002 RVA: 0x00009AA1 File Offset: 0x00007CA1
		protected virtual void ExtraAfterReadFromCoreServer(OperateResult read)
		{
		}

		/// <summary>
		/// 设置当前的登录的账户名和密码信息，并启用账户验证的功能，账户名为空时设置不生效<br />
		/// Set the current login account name and password information, and enable the account verification function. The account name setting will not take effect when it is empty
		/// </summary>
		/// <param name="userName">账户名</param>
		/// <param name="password">密码</param>
		// Token: 0x06001B5B RID: 7003 RVA: 0x00088034 File Offset: 0x00086234
		public void SetLoginAccount(string userName, string password)
		{
			bool flag = !string.IsNullOrEmpty(userName.Trim());
			if (flag)
			{
				this.isUseAccountCertificate = true;
				this.userName = userName;
				this.password = password;
			}
			else
			{
				this.isUseAccountCertificate = false;
			}
		}

		/// <summary>
		/// 认证账号，根据已经设置的用户名和密码，进行发送服务器进行账号认证。<br />
		/// Authentication account, according to the user name and password that have been set, sending server for account authentication.
		/// </summary>
		/// <param name="socket">套接字</param>
		/// <returns>认证结果</returns>
		// Token: 0x06001B5C RID: 7004 RVA: 0x00088078 File Offset: 0x00086278
		protected OperateResult AccountCertificate(Socket socket)
		{
			OperateResult operateResult = base.SendAccountAndCheckReceive(socket, 1, this.userName, this.password);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				OperateResult<int, string[]> operateResult2 = base.ReceiveStringArrayContentFromSocket(socket, 30000);
				bool flag2 = !operateResult2.IsSuccess;
				if (flag2)
				{
					result = operateResult2;
				}
				else
				{
					bool flag3 = operateResult2.Content1 == 0;
					if (flag3)
					{
						result = new OperateResult(operateResult2.Content2[0]);
					}
					else
					{
						result = OperateResult.CreateSuccessResult();
					}
				}
			}
			return result;
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.AccountCertificate(System.Net.Sockets.Socket)" />
		// Token: 0x06001B5D RID: 7005 RVA: 0x000880F4 File Offset: 0x000862F4
		[DebuggerStepThrough]
		protected Task<OperateResult> AccountCertificateAsync(Socket socket)
		{
			return Task.Run(()=>AccountCertificate(socket));
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.InitializationOnConnect(System.Net.Sockets.Socket)" />
		// Token: 0x06001B5E RID: 7006 RVA: 0x00088140 File Offset: 0x00086340
		[DebuggerStepThrough]
		protected virtual Task<OperateResult> InitializationOnConnectAsync(Socket socket)
		{
			return Task.Run(()=>InitializationOnConnect(socket));
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ExtraOnDisconnect(System.Net.Sockets.Socket)" />
		// Token: 0x06001B5F RID: 7007 RVA: 0x0008818C File Offset: 0x0008638C
		[DebuggerStepThrough]
		protected virtual Task<OperateResult> ExtraOnDisconnectAsync(Socket socket)
		{
			return Task.Run(()=>ExtraOnDisconnect(socket));
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.CreateSocketAndInitialication" />
		// Token: 0x06001B60 RID: 7008 RVA: 0x000881D8 File Offset: 0x000863D8
		[DebuggerStepThrough]
		private Task<OperateResult<Socket>> CreateSocketAndInitialicationAsync()
		{
			return Task.Run(() => CreateSocketAndInitialication());
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.GetAvailableSocket" />
		// Token: 0x06001B61 RID: 7009 RVA: 0x0008821C File Offset: 0x0008641C
		[DebuggerStepThrough]
		protected Task<OperateResult<Socket>> GetAvailableSocketAsync()
		{
			return Task.Run(()=>GetAvailableSocket());
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ConnectServer" />
		// Token: 0x06001B62 RID: 7010 RVA: 0x00088260 File Offset: 0x00086460
		[DebuggerStepThrough]
		public Task<OperateResult> ConnectServerAsync()
		{
			return Task.Run(()=>ConnectServer());
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ConnectClose" />
		// Token: 0x06001B63 RID: 7011 RVA: 0x000882A4 File Offset: 0x000864A4
		[DebuggerStepThrough]
		public Task<OperateResult> ConnectCloseAsync()
		{
			return Task.Run(()=>ConnectClose());
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ReadFromCoreServer(System.Net.Sockets.Socket,System.Byte[],System.Boolean,System.Boolean)" />
		// Token: 0x06001B64 RID: 7012 RVA: 0x000882E8 File Offset: 0x000864E8
		[DebuggerStepThrough]
		public virtual Task<OperateResult<byte[]>> ReadFromCoreServerAsync(Socket socket, byte[] send, bool hasResponseData = true, bool usePackHeader = true)
		{
			return Task.Run(()=>ReadFromCoreServer(socket, send, hasResponseData, usePackHeader));
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ReadFromCoreServer(System.Byte[],System.Boolean)" />
		// Token: 0x06001B65 RID: 7013 RVA: 0x0008834C File Offset: 0x0008654C
		[DebuggerStepThrough]
		public Task<OperateResult<byte[]>> ReadFromCoreServerAsync(byte[] send)
		{
			return Task.Run(()=>ReadFromCoreServer(send));
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ReadFromCoreServer(System.Byte[],System.Boolean)" />
		// Token: 0x06001B66 RID: 7014 RVA: 0x00088398 File Offset: 0x00086598
		[DebuggerStepThrough]
		public Task<OperateResult<byte[]>> ReadFromCoreServerAsync(byte[] send, bool hasResponseData)
		{
			return Task.Run(()=>ReadFromCoreServer(send, hasResponseData));
		}

		/// <summary>
		/// 对当前的命令进行打包处理，通常是携带命令头内容，标记当前的命令的长度信息，需要进行重写，否则默认不打包
		/// </summary>
		/// <param name="command">发送的数据命令内容</param>
		/// <returns>打包之后的数据结果信息</returns>
		// Token: 0x06001B67 RID: 7015 RVA: 0x000883EA File Offset: 0x000865EA
		protected virtual byte[] PackCommandWithHeader(byte[] command)
		{
			return command;
		}

		/// <summary>
		/// 获取本次操作的可用的网络通道，如果是短连接，就重新生成一个新的网络通道，如果是长连接，就复用当前的网络通道。<br />
		/// Obtain the available network channels for this operation. If it is a short connection, a new network channel is regenerated. 
		/// If it is a long connection, the current network channel is reused.
		/// </summary>
		/// <returns>是否成功，如果成功，使用这个套接字</returns>
		// Token: 0x06001B68 RID: 7016 RVA: 0x000883F0 File Offset: 0x000865F0
		protected OperateResult<Socket> GetAvailableSocket()
		{
			bool flag = this.isPersistentConn;
			OperateResult<Socket> result;
			if (flag)
			{
				bool flag2 = this.isUseSpecifiedSocket;
				if (flag2)
				{
					bool isSocketError = this.IsSocketError;
					if (isSocketError)
					{
						result = new OperateResult<Socket>(StringResources.Language.ConnectionIsNotAvailable);
					}
					else
					{
						result = OperateResult.CreateSuccessResult<Socket>(this.CoreSocket);
					}
				}
				else
				{
					bool flag3 = this.IsSocketError || this.CoreSocket == null;
					if (flag3)
					{
						OperateResult operateResult = this.ConnectServer();
						bool flag4 = !operateResult.IsSuccess;
						if (flag4)
						{
							this.IsSocketError = true;
							result = OperateResult.CreateFailedResult<Socket>(operateResult);
						}
						else
						{
							this.IsSocketError = false;
							result = OperateResult.CreateSuccessResult<Socket>(this.CoreSocket);
						}
					}
					else
					{
						result = OperateResult.CreateSuccessResult<Socket>(this.CoreSocket);
					}
				}
			}
			else
			{
				result = this.CreateSocketAndInitialication();
			}
			return result;
		}

		/// <summary>
		/// 尝试连接服务器，如果成功，并执行<see cref="M:HslCommunication.Core.Net.NetworkDoubleBase.InitializationOnConnect(System.Net.Sockets.Socket)" />的初始化方法，并返回最终的结果。<br />
		/// Attempt to connect to the server, if successful, and execute the initialization method of <see cref="M:HslCommunication.Core.Net.NetworkDoubleBase.InitializationOnConnect(System.Net.Sockets.Socket)" />, and return the final result.
		/// </summary>
		/// <returns>带有socket的结果对象</returns>
		// Token: 0x06001B69 RID: 7017 RVA: 0x000884BC File Offset: 0x000866BC
		private OperateResult<Socket> CreateSocketAndInitialication()
		{
			OperateResult<Socket> operateResult = base.CreateSocketAndConnect(new IPEndPoint(IPAddress.Parse(this.ipAddress), this.port), this.connectTimeOut);
			bool isSuccess = operateResult.IsSuccess;
			if (isSuccess)
			{
				OperateResult operateResult2 = this.InitializationOnConnect(operateResult.Content);
				bool flag = !operateResult2.IsSuccess;
				if (flag)
				{
					Socket content = operateResult.Content;
					if (content != null)
					{
						content.Close();
					}
					operateResult.IsSuccess = operateResult2.IsSuccess;
					operateResult.CopyErrorFromOther<OperateResult>(operateResult2);
				}
			}
			return operateResult;
		}

		/// <summary>
		/// 将数据报文发送指定的网络通道上，根据当前指定的<see cref="T:HslCommunication.Core.IMessage.INetMessage" />类型，返回一条完整的数据指令<br />
		/// Sends a data message to the specified network channel, and returns a complete data command according to the currently specified <see cref="T:HslCommunication.Core.IMessage.INetMessage" /> type
		/// </summary>
		/// <param name="socket">指定的套接字</param>
		/// <param name="send">发送的完整的报文信息</param>
		/// <param name="hasResponseData">是否有等待的数据返回，默认为 true</param>
		/// <param name="usePackHeader">是否需要对命令重新打包，在重写<see cref="M:HslCommunication.Core.Net.NetworkDoubleBase.PackCommandWithHeader(System.Byte[])" />方法后才会有影响</param>
		/// <remarks>
		/// 无锁的基于套接字直接进行叠加协议的操作。
		/// </remarks>
		/// <example>
		/// 假设你有一个自己的socket连接了设备，本组件可以直接基于该socket实现modbus读取，三菱读取，西门子读取等等操作，前提是该服务器支持多协议，虽然这个需求听上去比较变态，但本组件支持这样的操作。
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ReadFromCoreServerExample1" title="ReadFromCoreServer示例" />
		/// </example>
		/// <returns>接收的完整的报文信息</returns>
		// Token: 0x06001B6A RID: 7018 RVA: 0x00088544 File Offset: 0x00086744
		public virtual OperateResult<byte[]> ReadFromCoreServer(Socket socket, byte[] send, bool hasResponseData = true, bool usePackHeader = true)
		{
			ILogNet logNet = base.LogNet;
			if (logNet != null)
			{
				logNet.WriteDebug(this.ToString(), StringResources.Language.Send + " : " + (this.LogMsgFormatBinary ? send.ToHexString(' ') : Encoding.ASCII.GetString(send)));
			}
			INetMessage newNetMessage = this.GetNewNetMessage();
			bool flag = newNetMessage != null;
			if (flag)
			{
				newNetMessage.SendBytes = send;
			}
			OperateResult operateResult = base.Send(socket, usePackHeader ? this.PackCommandWithHeader(send) : send);
			bool flag2 = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag2)
			{
				result = OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			else
			{
				bool flag3 = this.receiveTimeOut < 0;
				if (flag3)
				{
					result = OperateResult.CreateSuccessResult<byte[]>(new byte[0]);
				}
				else
				{
					bool flag4 = !hasResponseData;
					if (flag4)
					{
						result = OperateResult.CreateSuccessResult<byte[]>(new byte[0]);
					}
					else
					{
						bool flag5 = this.SleepTime > 0;
						if (flag5)
						{
							Thread.Sleep(this.SleepTime);
						}
						OperateResult<byte[]> operateResult2 = base.ReceiveByMessage(socket, this.receiveTimeOut, newNetMessage, null);
						bool flag6 = !operateResult2.IsSuccess;
						if (flag6)
						{
							result = operateResult2;
						}
						else
						{
							ILogNet logNet2 = base.LogNet;
							if (logNet2 != null)
							{
								logNet2.WriteDebug(this.ToString(), StringResources.Language.Receive + " : " + (this.LogMsgFormatBinary ? operateResult2.Content.ToHexString(' ') : Encoding.ASCII.GetString(operateResult2.Content)));
							}
							bool flag7 = newNetMessage != null && !newNetMessage.CheckHeadBytesLegal(base.Token.ToByteArray());
							if (flag7)
							{
								if (socket != null)
								{
									socket.Close();
								}
								result = new OperateResult<byte[]>(string.Concat(new string[]
								{
									StringResources.Language.CommandHeadCodeCheckFailed,
									Environment.NewLine,
									StringResources.Language.Send,
									": ",
									SoftBasic.ByteToHexString(send, ' '),
									Environment.NewLine,
									StringResources.Language.Receive,
									": ",
									SoftBasic.ByteToHexString(operateResult2.Content, ' ')
								}));
							}
							else
							{
								result = OperateResult.CreateSuccessResult<byte[]>(operateResult2.Content);
							}
						}
					}
				}
			}
			return result;
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ReadFromCoreServer(System.Byte[],System.Boolean)" />
		// Token: 0x06001B6B RID: 7019 RVA: 0x00088772 File Offset: 0x00086972
		public OperateResult<byte[]> ReadFromCoreServer(byte[] send)
		{
			return this.ReadFromCoreServer(send, true);
		}

		/// <summary>
		/// 将数据发送到当前的网络通道中，并从网络通道中接收一个<see cref="T:HslCommunication.Core.IMessage.INetMessage" />指定的完整的报文，网络通道将根据<see cref="M:HslCommunication.Core.Net.NetworkDoubleBase.GetAvailableSocket" />方法自动获取，本方法是线程安全的。<br />
		/// Send data to the current network channel and receive a complete message specified by <see cref="T:HslCommunication.Core.IMessage.INetMessage" /> from the network channel. 
		/// The network channel will be automatically obtained according to the <see cref="M:HslCommunication.Core.Net.NetworkDoubleBase.GetAvailableSocket" /> method This method is thread-safe.
		/// </summary>
		/// <param name="send">发送的完整的报文信息</param>
		/// <param name="hasResponseData">是否有等待的数据返回，默认为 true</param>
		/// <returns>接收的完整的报文信息</returns>
		/// <remarks>
		/// 本方法用于实现本组件还未实现的一些报文功能，例如有些modbus服务器会有一些特殊的功能码支持，需要收发特殊的报文，详细请看示例
		/// </remarks>
		/// <example>
		/// 此处举例有个modbus服务器，有个特殊的功能码0x09，后面携带子数据0x01即可，发送字节为 0x00 0x00 0x00 0x00 0x00 0x03 0x01 0x09 0x01
		/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Core\NetworkDoubleBase.cs" region="ReadFromCoreServerExample2" title="ReadFromCoreServer示例" />
		/// </example>
		// Token: 0x06001B6C RID: 7020 RVA: 0x0008877C File Offset: 0x0008697C
		public OperateResult<byte[]> ReadFromCoreServer(byte[] send, bool hasResponseData)
		{
			OperateResult<byte[]> operateResult = new OperateResult<byte[]>();
			OperateResult<Socket> operateResult2 = null;
			this.InteractiveLock.Enter();
			try
			{
				operateResult2 = this.GetAvailableSocket();
				bool flag = !operateResult2.IsSuccess;
				if (flag)
				{
					this.IsSocketError = true;
					AlienSession alienSession = this.AlienSession;
					if (alienSession != null)
					{
						alienSession.Offline();
					}
					this.InteractiveLock.Leave();
					operateResult.CopyErrorFromOther<OperateResult<Socket>>(operateResult2);
					return operateResult;
				}
				OperateResult<byte[]> operateResult3 = this.ReadFromCoreServer(operateResult2.Content, send, hasResponseData, true);
				bool isSuccess = operateResult3.IsSuccess;
				if (isSuccess)
				{
					this.IsSocketError = false;
					operateResult.IsSuccess = operateResult3.IsSuccess;
					operateResult.Content = operateResult3.Content;
					operateResult.Message = StringResources.Language.SuccessText;
				}
				else
				{
					this.IsSocketError = true;
					AlienSession alienSession2 = this.AlienSession;
					if (alienSession2 != null)
					{
						alienSession2.Offline();
					}
					operateResult.CopyErrorFromOther<OperateResult<byte[]>>(operateResult3);
				}
				this.ExtraAfterReadFromCoreServer(operateResult3);
				this.InteractiveLock.Leave();
			}
			catch
			{
				this.InteractiveLock.Leave();
				throw;
			}
			bool flag2 = !this.isPersistentConn;
			if (flag2)
			{
				if (operateResult2 != null)
				{
					Socket content = operateResult2.Content;
					if (content != null)
					{
						content.Close();
					}
				}
			}
			return operateResult;
		}

		/// <summary>
		/// 释放当前的资源，并自动关闭长连接，如果设置了的话
		/// </summary>
		/// <param name="disposing">是否释放托管的资源信息</param>
		// Token: 0x06001B6D RID: 7021 RVA: 0x000888C4 File Offset: 0x00086AC4
		protected virtual void Dispose(bool disposing)
		{
			bool flag = !this.disposedValue;
			if (flag)
			{
				if (disposing)
				{
					this.ConnectClose();
					SimpleHybirdLock interactiveLock = this.InteractiveLock;
					if (interactiveLock != null)
					{
						interactiveLock.Dispose();
					}
				}
				this.disposedValue = true;
			}
		}

		/// <summary>
		/// 释放当前的资源
		/// </summary>
		// Token: 0x06001B6E RID: 7022 RVA: 0x00088908 File Offset: 0x00086B08
		public void Dispose()
		{
			this.Dispose(true);
		}

		/// <inheritdoc />
		// Token: 0x06001B6F RID: 7023 RVA: 0x00088914 File Offset: 0x00086B14
		public override string ToString()
		{
			return string.Format("NetworkDoubleBase<{0}, {1}>[{2}:{3}]", new object[]
			{
				this.GetNewNetMessage().GetType(),
				this.ByteTransform.GetType(),
				this.IpAddress,
				this.Port
			});
		}

		// Token: 0x040005F0 RID: 1520
		private IByteTransform byteTransform;

		// Token: 0x040005F1 RID: 1521
		private string ipAddress = "127.0.0.1";

		// Token: 0x040005F2 RID: 1522
		private int port = 10000;

		// Token: 0x040005F3 RID: 1523
		private int connectTimeOut = 10000;

		// Token: 0x040005F4 RID: 1524
		private string connectionId = string.Empty;

		// Token: 0x040005F5 RID: 1525
		private bool isUseSpecifiedSocket = false;

		/// <summary>
		/// 接收数据的超时时间，单位：毫秒
		/// <br />
		/// Timeout for receiving data, unit: millisecond
		/// </summary>
		// Token: 0x040005F6 RID: 1526
		protected int receiveTimeOut = 5000;

		/// <summary>
		/// 是否是长连接的状态<br />
		/// Whether it is a long connection state
		/// </summary>
		// Token: 0x040005F7 RID: 1527
		protected bool isPersistentConn = false;

		/// <summary>
		/// 交互的混合锁，保证交互操作的安全性<br />
		/// Interactive hybrid locks to ensure the security of interactive operations
		/// </summary>
		// Token: 0x040005F8 RID: 1528
		protected SimpleHybirdLock InteractiveLock;

		/// <summary>
		/// 指示长连接的套接字是否处于错误的状态<br />
		/// Indicates if the long-connected socket is in the wrong state
		/// </summary>
		// Token: 0x040005F9 RID: 1529
		protected bool IsSocketError = false;

		/// <summary>
		/// 设置日志记录报文是否二进制，如果为False，那就使用ASCII码<br />
		/// Set whether the log message is binary, if it is False, then use ASCII code
		/// </summary>
		// Token: 0x040005FA RID: 1530
		protected bool LogMsgFormatBinary = true;

		/// <summary>
		/// 是否使用账号登录，这个账户登录的功能是<c>HSL</c>组件创建的服务器特有的功能。<br />
		/// Whether to log in using an account. The function of this account login is a server-specific function created by the <c> HSL </c> component.
		/// </summary>
		// Token: 0x040005FD RID: 1533
		protected bool isUseAccountCertificate = false;

		// Token: 0x040005FE RID: 1534
		private string userName = string.Empty;

		// Token: 0x040005FF RID: 1535
		private string password = string.Empty;

		// Token: 0x04000600 RID: 1536
		private bool disposedValue = false;

		// Token: 0x04000601 RID: 1537
		private Lazy<Ping> ping = new Lazy<Ping>(() => new Ping());
	}
}
